#include "struct.h"

int left_turn(const point& a, const point& b, const point& c)
{
	const double eps = 4 * std::numeric_limits<double>::epsilon();
	double part1 = (b.x - a.x) * (c.y - a.y);
	double part2 = (b.y - a.y) * (c.x - a.x);
    double left_turn = part1 - part2;

    if (eps * (std::abs(part1) + std::abs(part2)) < left_turn)
        return 1;
    if (eps * (std::abs(part1) + std::abs(part2)) <= -left_turn)
        return -1;
    return 0;													//maybe not enough accuracy
}

double sqr_radius(const point& a)
{
	point b = point(0.0, 0.0);
	return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

bool point_in_circle(const point& p, const circle& circ)
{
    switch(circ.border.size())
    {
		case 1:
			return p == circ.border[0];
		case 2:
		{
			double r_a = sqr_radius(circ.border[0]);
			double r_b = sqr_radius(circ.border[1]);
			double r_p = sqr_radius(p);

			return r_a + r_b >= r_p;
		}
		case 3:
		{
			point a = circ.border[0]; point b = circ.border[1]; point c = circ.border[2];

			double r_a = sqr_radius(a);
			double r_b = sqr_radius(b);
			double r_c = sqr_radius(c);

			double first_det = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
			double second_det = (r_b - r_a) * (c.y - a.y) - (b.y - a.y) * (r_c - r_a);
			double third_det = (r_b - r_a) * (c.x - a.x) - (b.x - a.x) * (r_c - r_a);
			double fourth_det;

			double det_part1 = (b.x * c.y - c.x * b.y) * r_a;
			double det_part2 = (r_b * c.y - r_c * b.y) * a.x;
			double det_part3 = (r_b * c.x - r_c * b.x) * a.y;
			fourth_det = det_part1 - det_part2 + det_part3;

			double r = std::pow(hypot(p.x, p.y), 2);
			double tmp = first_det * r - second_det * p.x + third_det * p.y - fourth_det;

			int result = tmp / std::abs(tmp);
			int sign_first_det = first_det / std::abs(first_det);
			return result * sign_first_det <= 0;				//maybe not enough accuracy = )
		}
		default:
			return false;
    }
}